/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package evabot.xml;

//package alicebot.xml;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
 * Classe responsÃ¡vel pelo controle da criaÃ§Ã£o e manipulaÃ§Ã£o de arquivos AIML;
 *
 * @author Alexandre Sales, Danielle Chaves, Maria Isabel Farias
 *
 */
public class AIMLController{

	private AIMLEditor aimlEditor;
	private final String fileSeparator = System.getProperty("file.separator");
	private Document doc;
	private String fileName;
	private static AIMLController instance = null;
	Element rootNode;


	private AIMLController() { }

	/**
	 * ResponsÃ¡vel pela criaÃ§Ã£o de uma instÃ¢ncia da classe AIMLController.
	 *
	 * @return Uma instancia controladora de AIML.
	 */
	public static AIMLController getInstance() {
		if(instance == null) {
			return new AIMLController();
		}
		return instance;
	}

	/**
	 * Cria um arquivo AIML em branco.
	 *
	 */
	public boolean createBlanckAIMLFile() {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.newDocument();
			Node raiz = document.createElement("aiml");
			Node no1 = document.createTextNode("\n ");
			raiz.appendChild(no1);
			document.appendChild(raiz);

			TransformerFactory transFactory = TransformerFactory.newInstance();
			Transformer transformer = transFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");

			File file = new File("Bot"+fileSeparator+"Alice"+fileSeparator+fileName+".aiml");

			StreamResult result = new StreamResult(file);

			DOMSource source = new DOMSource(document);
			transformer.transform(source, result);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * Abre um arquivo AIML.
	 *
	 * @throws ParserConfigurationException
	 * 		Caso nÃ£o seja possÃ­vel carregar ou instaciar uma classe parser.
	 * @throws IOException
	 * 		Erro de entrada/saida.
	 * @throws SAXException
	 * 		Caso o XML nÃ£o se comporte como o esperado.
	 */
	public void openAIML(String fileInput) throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		factory.setNamespaceAware(true);
		factory.setIgnoringElementContentWhitespace(true);

		DocumentBuilder builder = factory.newDocumentBuilder();

		this.doc = builder.parse( new File("Bot"+fileSeparator+"Alice"+fileSeparator+fileInput+".aiml") );
		this.rootNode = doc.getDocumentElement();

		aimlEditor = new AIMLEditor(this.doc);

	}

	/**
	 * Salva o arquivo AIML.
	 *
	 * @return  Retorna true, caso o arquivo seja salvo com sucesso;
	 * 			Retorna false, caso contrÃ¡rio.
	 */
	public boolean saveAIML(String fileOutput) {

		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");

			StreamResult result = new StreamResult(new File("Bot"+fileSeparator+"Alice"+fileSeparator+fileOutput+".aiml"));

			DOMSource source = new DOMSource(getDocument());

			transformer.transform(source, result);

			return true;

		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * ResponsÃ¡vel pela recuperaÃ§Ã£o do documento DOM que estÃ¡ sendo manipulado.
	 *
	 * @return O documento que estÃ¡ sendo manipulado.
	 */
	public Document getDocument() {
		return this.doc;
	}

	/**
	 * AdiÃ§Ã£o de nova categoria ao documento AIML.
	 *
	 * @param fileName
	 * 			Nome do arquivo a ser acrescentado a nova categoria.
	 * @param question
	 * 			A pergunta a ser inserida na tag <pattern> da categoria.
	 * @param answer
	 * 			A resposta a ser inserida na tag <template> da categoria.
	 *
	 * @throws SAXException
	 * 			Caso haja algum erro ou aviso SAX.
	 * @throws ParserConfigurationException
	 * 			Caso haja algum erro na configuraÃ§Ã£o do Parser do Chatterbean.
	 * @throws IOException
	 * 			Erro de entrada/saida.
	 */
	public void setNewCategory(String fileName, String question, String answer) throws ParserConfigurationException, SAXException, IOException {
		openAIML(fileName);
		aimlEditor.insertCategory(question, answer);
		saveAIML(fileName);
	}

	/**
	 * Seta o nome do arquivo AIML a ser criado e manipulado.
	 *
	 * @param fileName
	 * 			O nome do arquivo desejado.
	 */
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

}
